grammar GammaPomset;

options {
  language = Java;
  // generated parser should create abstract syntax tree
  //output = AST;
}

@lexer::header {
  package lifo.GammaTaf.GammaPomset.parsers;  
}


@parser::header {
  package lifo.GammaTaf.GammaPomset.parsers;
  import lifo.GammaTaf.GammaPomset.GammaPomset;
}
@parser::members {
  GammaPomset res;
  
  public static GammaPomset parserString(String s) throws Exception {
    CharStream input = new ANTLRStringStream(s);
    return parser(input);       
  }

  public static GammaPomset parserFile(String s) throws Exception {
    CharStream input = new ANTLRFileStream(s);
    return parser(input);       
  }
  
  public static GammaPomset parser(CharStream input) throws Exception {
    GammaPomsetLexer lexer = new GammaPomsetLexer(input);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    GammaPomsetParser parser = new GammaPomsetParser(tokens);
    parser.rule();
       
    return parser.res;
  }
 
}

// parser rules
rule : expression
  {
    res = $expression.b;
  }
  ;

expression returns [GammaPomset b]
  : s0=serie 
    {
    $b = $s0.b;
    ArrayList<GammaPomset> arg = new ArrayList<GammaPomset>();
    arg.add($b);
  }
  ('+' s1=serie
  {
    arg.add($s1.b);
  }
  )*
  {
    if (arg.size() > 1)
      $b = new GammaPomset.Sum(arg.toArray(new GammaPomset[]{}));
  };

serie returns [GammaPomset b]
  : s0=star 
  {
    $b = $s0.b;
    ArrayList<GammaPomset> arg = new ArrayList<GammaPomset>();
    arg.add($b);
  }
  ('.'s1=star
   {
    arg.add($s1.b);
  }  
  )*
    {
    if (arg.size() > 1)
      $b = new GammaPomset.Serie(arg.toArray(new GammaPomset[]{}));
  }
  ;

star returns [GammaPomset b]
  : atom 
  {
    $b = $atom.b;
  }
  (STAR
  {
    $b = new GammaPomset.Star($b);
  }
  )?;

atom returns [GammaPomset b]
  : '(' GAMMA ',' ID ',' GAMMA ')'
  {
    $b = new GammaPomset.Action($ID.text);
  }
  | '(' expression ')'
  {
    $b = $expression.b;
  };

//lexer rules
GAMMA : '{'(('0'..'9')*|' ')(','(('0'..'9')*|' '))*'}';
ID  : ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
STAR : '*';

//Ignore white spaces
WS : ( ' ' | '\t' | '\r' | '\n' )+ { $channel = HIDDEN; };